package darlingbastard.stacks;

import javax.servlet.jsp.PageContext;
import java.util.Stack;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by bishope
 * Date: Mar 13, 2006
 */
public class TowerSupport {
    private static String ATTRIBUTE_KEY = TowerSupport.class.getName();

    private final PageContext page;
    private Stack selectStack = new Stack();
    private Stack envStack = new Stack();

    public TowerSupport(PageContext page) {
        this.page = page;
        this.envStack.push(new Env(null));
    }

    public void select(String path) {
        selectStack.push(path);
    }

    public void unselect() {
        selectStack.pop();
    }

    public void pushEnv() {
        envStack.push(new HashMap());
    }

    public void popEnv() {
        envStack.pop();
    }

    public Object evaluatePath(String relativePath) {
        String path = toAbsolutePath(relativePath);
        return find(path);
    }

    private Object find(String path) {
        return getEnv().find(path);
    }

    private String toAbsolutePath(String relativePath) {
        return relativePath;
    }

    public static TowerSupport get(PageContext page) {
        synchronized(page) {
            TowerSupport instance = (TowerSupport) page.getAttribute(ATTRIBUTE_KEY, PageContext.REQUEST_SCOPE);
            if (instance == null) {
                instance = new TowerSupport(page);
                page.setAttribute(ATTRIBUTE_KEY, PageContext.REQUEST_SCOPE);
            }
            return instance;
        }
    }

    private Env getEnv() {
        return (Env)envStack.peek();
    }

    public class Env {
        Env parent;
        Map map = new HashMap();

        public Env(Env parent) {
            this.parent = parent;
        }

        public Object find(String path) {
            if (parent == null) {
                Object result = page.getAttribute(path);
                if (result != null) return result;
            } else {
                Object result = parent.find(path);
                if (result != null) return result;
            }
            return map.get(path);
        }
    }

}
